package com.lagou.factory;

import com.lagou.annotion.Autowired;
import com.lagou.annotion.Comppent;
import com.lagou.annotion.Transactional;
import com.lagou.util.PlatformTrancationManager;
import com.lagou.util.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Authther: mrwu
 * @date:2021/3/13-03
 * @Description:com.lagou.factory
 */
@Comppent
public class ProxyFactory {

//单例模式下
//    private static ProxyFactory proxyFactory =new ProxyFactory();
//
//    private ProxyFactory() {
//    }
//
//    public static ProxyFactory getInstance(){
//        return proxyFactory;
//    }
    //单例模式下
//    private TransactionManager transactionManager=TransactionManager.getTransactionManager();
    //IOC方式下
//    @Autowired
//    private TransactionManager transactionManager;
    @Autowired
    private PlatformTrancationManager transactionManager;

    /**
     *
     * @param target 实现了接口的具体类的对象 委托对象
     * @return //返回一个实现了某些接口的代理对象
     */
    public  Object getJDKProxy(Object target){
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try {
                    method.invoke(target, args);
                    transactionManager.commit();
                }catch (Exception e){
                    e.printStackTrace();
                    transactionManager.rollback();
                    throw e.getCause();
                }

                return proxy;
            }
        };
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),invocationHandler);
    }


    public Object getCGlibProxy(Object target){
        return  Enhancer.create(target.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

                Object proxy =null;
               //对方法进行过滤,如果当前方法的类被注解或当前方法被注解都进入事务控制
                if (method.getDeclaringClass().isAnnotationPresent(Transactional.class)|method.isAnnotationPresent(Transactional.class)){
                    try {
                        System.out.println("cglib");
                        proxy = methodProxy.invokeSuper(o,objects);  //调用父类方法
                        transactionManager.commit();
                    }catch (Exception e){
                        transactionManager.rollback();
                        throw e.getCause();
                    }
                }else {
                    proxy = methodProxy.invokeSuper(o,objects);
                }
                return proxy;
            }
        });
    }
}
